package com.zzz.poker.netty.configuration;

import com.zzz.poker.properties.WebSocketProperties;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

/**
 * Netty WebSocket 服务器配置
 */
@Component
public class NettyConfig {
    private static final Logger logger = LoggerFactory.getLogger(NettyConfig.class);

    private final WebSocketProperties properties;
    private final WebSocketInitializer webSocketInitializer;
    
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Channel serverChannel;

    @Autowired
    public NettyConfig(WebSocketProperties properties, WebSocketInitializer webSocketInitializer) {
        this.properties = properties;
        this.webSocketInitializer = webSocketInitializer;
    }

    /**
     * 启动 Netty 服务器
     */
    public void start() {
        logger.info("Starting Netty WebSocket server on port: {}", properties.getPort());
        
        // 配置线程组
        bossGroup = new NioEventLoopGroup(properties.getBossThreads());
        workerGroup = new NioEventLoopGroup(properties.getWorkerThreads());
        
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(properties.getPort()))
                    .option(ChannelOption.SO_BACKLOG, properties.getSoBacklog())
                    .childOption(ChannelOption.SO_KEEPALIVE, properties.isSoKeepalive())
                    .childHandler(webSocketInitializer);
            
            // 绑定端口并启动服务器
            ChannelFuture future = bootstrap.bind().sync();
            serverChannel = future.channel();
            
            logger.info("Netty WebSocket server started on port: {}", properties.getPort());
            
            // 注册关闭钩子
            Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
            
            // 等待服务器通道关闭
            serverChannel.closeFuture().sync();
        } catch (InterruptedException e) {
            logger.error("Netty server interrupted", e);
            Thread.currentThread().interrupt();
        } finally {
            shutdown();
        }
    }

    /**
     * 优雅关闭 Netty 服务器
     */
    @PreDestroy
    public void shutdown() {
        logger.info("Shutting down Netty WebSocket server...");
        
        if (serverChannel != null) {
            serverChannel.close();
        }
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        
        logger.info("Netty WebSocket server shutdown completed");
    }
}